package org.example.authservice.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpSession;
import jakarta.validation.constraints.Pattern;
import org.example.authservice.anno.Debounce;
import org.example.authservice.anno.MyLog;
import org.example.authservice.pojo.*;
import org.example.authservice.service.MailService;
import org.example.authservice.service.RoleService;
import org.example.authservice.service.UserRoleService;
import org.example.authservice.service.UserService;
import org.example.authservice.utils.*;
import org.example.authservice.vo.AssignTreeVO;
import org.hibernate.validator.constraints.URL;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.util.StringUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author 浦慧慧
 * @since 2024/12/15 11.34
 * @version 1.0
 */
@RestController
@RequestMapping("/users")
@Validated
public class UserController {

    Logger logger = LoggerFactory.getLogger(UserController.class);

    @Resource
    private UserService userService;

    @Resource
    private UserRoleService userRoleService;

    @Resource
    private RoleService roleService;

    @Resource
    private MailService mailService;

    @Resource
    private StringRedisTemplate stringRedisTemplate;

    @MyLog(content = "操作模块", title = "用户注册")
    @PostMapping
    public Result<?> register(@Pattern(regexp = "^\\S{2,30}$", message = "用户名必须是2到30个非空白字符") String username,
                              @Pattern(regexp = "^\\S{5,16}$", message = "密码必须是5到16个非空白字符") String password) {
        UserContextHolder.setUser(username);
        //查询用户
        //测试1
        User u = userService.findByUserName(username);
        if (u == null) {
            //没有占用
            //注册
            userService.register(username, password);
            //添加权限
            User user = userService.findByUserName(username);
            UserRole userRole = new UserRole();
            userRole.setRoleId(2);
            userRole.setUserId(user.getId());
            userRoleService.save(userRole);
            return Result.success();
        } else {
            //占用
            logger.error("用户名已被占用");
            return Result.error("用户名已被占用");
        }
    }

    @Debounce()
    @MyLog(content = "登录模块", title = "用户登录")
    @PostMapping("/login")
    public Result<?> login(@RequestBody User user) {
        UserContextHolder.setUser(user.getUsername());
        //根据用户名查询用户
        User loginUser = userService.findByUserName(user.getUsername());
        //判断该用户是否存在
        if (loginUser == null) {
            return Result.error("用户名或密码错误");
        }
        //解密
        String decryptPassword = Objects.requireNonNull(AESUtil.decrypt(user.getPassword())).toString();

        //判断密码是否正确  loginUser对象中的password是密文
        if (Md5Util.getMD5String(decryptPassword).equals(loginUser.getPassword())) {
            //登录成功
            Map<String, Object> claims = new HashMap<>(1);
            claims.put("id", loginUser.getId());
            claims.put("username", loginUser.getUsername());
            String token = JwtUtil.genToken(claims);
            //把token存储到redis中
            try{
                ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
                operations.set(token,token,1, TimeUnit.HOURS);
                return Result.success(token);
            } catch (Exception e) {
                return Result.error("redis未启动");
            }
        }
        return Result.error("用户名或密码错误");
    }

    @Debounce()
    @GetMapping("/userinfo/{username}")
    public Result<User> userInfo(@PathVariable String username) {
        //根据用户名查询用户
        User user = userService.findByUserName(username);
        return Result.success(user);
    }

    @MyLog(content = "操作模块", title = "用户更新邮箱")
    @Debounce()
    @PutMapping("/userinfo")
    public Result<?> update(@RequestBody @Validated User user) {
        User findUser = userService.findByInput(user.getEmail());
        if(findUser != null){
            return Result.error("该邮箱已被注册");
        }
        userService.update(user);
        return Result.success();
    }

    @MyLog(content = "操作模块", title = "用户更新头像")
    @Debounce()
    @PatchMapping("/avatar")
    public Result<?> updateAvatar(@RequestParam @URL String avatarUrl) {
        userService.updateAvatar(avatarUrl);
        return Result.success();
    }

    @MyLog(content = "操作模块", title = "用户更新密码")
    @Debounce()
    @PatchMapping("/password")
    public Result<?> updatePwd(@RequestBody Map<String, String> params,@RequestHeader("Authorization") String token) {
        //1.校验参数
        String oldPwd = params.get("old_pwd");
        String newPwd = params.get("new_pwd");
        String rePwd = params.get("re_pwd");

        if (!StringUtils.hasLength(oldPwd) || !StringUtils.hasLength(newPwd) || !StringUtils.hasLength(rePwd)) {
            return Result.error("缺少必要的参数");
        }

        //原密码是否正确
        //调用userService根据用户名拿到原密码,再和old_pwd比对
        Map<String,Object> map = ThreadLocalUtil.get();
        String username = (String) map.get("username");
        User loginUser = userService.findByUserName(username);
        if (!loginUser.getPassword().equals(Md5Util.getMD5String(oldPwd))){
            return Result.error("原密码填写不正确");
        }

        //newPwd和rePwd是否一样
        if (!rePwd.equals(newPwd)){
            return Result.error("两次填写的新密码不一样");
        }

        //2.调用service完成密码更新
        userService.updatePwd(newPwd);
        //删除redis中对应的token
        ValueOperations<String, String> operations = stringRedisTemplate.opsForValue();
        operations.getOperations().delete(token);
        return Result.success();
    }

    @MyLog(content = "操作模块", title = "新增用户")
    @PostMapping("/newuser")
    public Result<?> add(@RequestBody User user){
        user.setCreateTime(LocalDateTime.now());
        user.setUpdateTime(LocalDateTime.now());
        userService.saveUser(user);
        return Result.success("新增成功");
    }

    @Debounce()
    @PutMapping
    public Result<?> edit(@RequestBody User user){
        user.setUpdateTime(LocalDateTime.now());
        userService.editUser(user);
        return Result.success("编辑成功");
    }

    @MyLog(content = "操作模块", title = "删除用户")
    @Debounce()
    @DeleteMapping("/{userId}")
    public Result<?> delete(@PathVariable Long userId){
        userService.deleteUser(Math.toIntExact(userId));
        return Result.success("删除成功");
    }

    @Debounce()
    @GetMapping
    public Result<?> list(UserPage parm){
        // 构造查询条件
        QueryWrapper<User> query = new QueryWrapper<>();
        if(parm.getUsername() != null && !parm.getUsername().isEmpty()){
            query.lambda().like(User::getUsername, parm.getUsername());
        }
        query.lambda().orderByDesc(User::getCreateTime);
        List<User> users = userService.list(query);
        if (users.isEmpty()) {
            return Result.error("没有该用户");
        }
        // 获取所有用户的ID
        List<Integer> userIds = users.stream().map(User::getId).collect(Collectors.toList());

        // 查询所有用户的角色
        QueryWrapper<UserRole> userRoleQuery = new QueryWrapper<>();
        userRoleQuery.lambda().in(UserRole::getUserId, userIds);
        List<UserRole> userRoles = userRoleService.list(userRoleQuery);

        // 获取所有相关角色的ID
        List<Integer> roleIds = userRoles.stream().map(UserRole::getRoleId).distinct().collect(Collectors.toList());

        // 查询所有相关角色
        QueryWrapper<Role> roleQuery = new QueryWrapper<>();
        roleQuery.lambda().in(Role::getId, roleIds);
        List<Role> roles = roleService.list(roleQuery);

        // 将角色列表添加到每个用户对象中
        users.forEach(user -> {
            List<Role> userRolesList = userRoles.stream()
                    .filter(ur -> ur.getUserId().equals(user.getId()))
                    .map(ur -> roles.stream().filter(r -> r.getId().equals(ur.getRoleId())).findFirst().orElse(null))
                    .filter(Objects::nonNull) // 过滤掉可能为null的角色
                    .collect(Collectors.toList());
            user.setRoles(userRolesList);
        });

        // 返回结果
        return Result.success(users);
    }
    @Debounce()
    @GetMapping("/rolelist/{userId}")
    public Result<?> getRoleList(@PathVariable Long userId){
        QueryWrapper<UserRole> query = new QueryWrapper<>();
        query.lambda().eq(UserRole::getUserId, userId);
        List<UserRole> list= userRoleService.list(query);
        List<Integer> roleList = new ArrayList<>();
        System.out.println(list);
        Optional.ofNullable(list).orElse(new ArrayList<>())
                .forEach(item -> roleList.add(item.getRoleId()));
        return Result.success(roleList);
    }
    @Debounce()
    @GetMapping("/assignTree/{userId}/{roleId}")
    public Result<?> getAssignTree(@PathVariable Integer userId, @PathVariable Integer roleId){
        AssignTreeParm parm = new AssignTreeParm();
        parm.setUserId(userId);
        parm.setRoleId(roleId);
        AssignTreeVO assignTree = userService.getAssignTree(parm);
        return Result.success(assignTree);
    }

    @GetMapping("/getUsername")
    public Result<String> getUsername(HttpSession httpSession) {
        return Result.success((String) httpSession.getAttribute("currentUser"));
    }

    @Debounce()
    @GetMapping("/email")
    public Object emailCode(@RequestParam String email) throws Exception {
        Boolean b = mailService.getMailVc(email);
        if (b) {
            return Result.success("验证码已发送");
        } else {
            return Result.error("邮箱未被注册");
        }
    }

    @Debounce()
    @PatchMapping("/forgetpassword")
    public Result<?> resetPwd(@RequestBody RePassword rePassword){
        String redisCode = mailService.getRedisCode(rePassword.getEmail());
        if (!StringUtils.hasLength(redisCode)){
            return Result.error("验证码未获取或已过期");
        }
        if (redisCode.equals(rePassword.getCode())){
            if (!rePassword.getNewPwd().equals(rePassword.getRePwd())){
                return Result.error("两次密码不一致");
            }else{
                //解密
                String decryptPassword = Objects.requireNonNull(AESUtil.decrypt(rePassword.getNewPwd())).toString();
                userService.updateforgotPwd(rePassword.getEmail(),decryptPassword);
                mailService.removeRedisCode(rePassword.getEmail());
                return Result.success("密码重置成功");
            }
        }else{
            return Result.error("验证码错误");
        }
    }
    @GetMapping("/username/{email}")
    public Result<String> getUsername1(@PathVariable String email) {
        User user = userService.findByInput(email);
        return Result.success(user.getUsername());
    }
}


